Next | Prev | Up | Top | Contents | Index

Dynamic Loading Under Program Control

IRIX provides a library interface to the run-time linker that allows programs to load and unload DSOs dynamically. The functions in this interface are part of libc (see Table 3-1).

Functions to Load/Unload DSOs
dlopen()Load a DSO
dlsym()Find a symbol in a loaded DSO
dlclose()Unload a DSO
dlerror()Report errors

To load a DSO, call dlopen():

include <dlfcn.h>
void *dlhandle;
   ..
dlhandle = dlopen("/usr/lib/mylib.so", RTLD_LAZY);
if (dlhandle == NULL) {
   /* couldn't open DSO */
   printf("Error: %s\n", dlerror());
}
The first argument to dlopen() is the pathname of the DSO to be loaded. This may be either an absolute or a relative pathname. When you call this routine, the run-time linker tries to load the specified DSO. If any unresolved references exist in the executable that are defined in the DSO, the run-time linker resolves these references on demand. You can also use dlsym() to access symbols in the DSO, whether or not the symbols are referenced in your executable.

When a DSO is brought into the address space of a process, it may contain references to symbols whose addresses are not known until the object is loaded. These references must be relocated before the symbols can be accessed. The second argument to dlopen() governs when these relocations take place.

This argument can have the following values:

RTLD_LAZY

Under this mode, only references to data symbols are relocated when the object is loaded. References to functions are not relocated until a given function is invoked for the first time. This mode may result in better performance, since a process may not reference all of the functions in any given shared object.

RTLD_NOW

Under this mode, all necessary relocations are performed when the object is first loaded. This may result in some wasted effort if relocations are performed for functions that are never referenced. However, this option is useful for applications that need to know as soon as an object is loaded that all symbols referenced during execution will be available.
You can also dynamically load shared objects by using sgidladd(), which is similar to dlopen(). However, unlike dlopen(), all the names in the shared object become available to satisfy references in shared objects during lazy text resolution. Furthermore, it's not necessary to use dlsym() to gain access to the symbols in the shared object. sgidladd() is available as part of libc. For more information, see the sgidladd(3) reference page.

To access symbols that are not referenced in your program, use dlsym():

#include <dlfcn.h>
void *dlhandle;
int (*funcptr)(int);
int i,j;
   .. load DSO ... 
funcptr = (int (*)(int)) dlsym(dlhandle, "factorial");
if (funcptr == NULL) {
   /* couldn't locate the symbol */
   exit();
}
i = (*funcptr)(j);
This example looks up the address of the function factorial() and assigns it to the function pointer funcptr.

If you encounter an error (dlopen() or dlsym() returns NULL), you can get diagnostic information by calling dlerror(). The dlerror() function returns a string describing the cause of the latest error. You should call dlerror() only after an error has occurred; at other times, its return value is undefined.

To unload a DSO, call dlclose():

#include <dlfcn.h>
void *dlhandle;
... load DSO, use DSO symbols ...
dlclose(dlhandle);
The dlclose function frees up the virtual address space that has been mmaped by the dlopen call of that file (similar to a munmap call). The difference, however, is that a dlclose on a file that has been opened multiple times (either through dlopen or program startup) does not cause the file to be munmaped until the file is no longer needed by the process.



Next | Prev | Up | Top | Contents | Index